home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 2010 April / PCWorld0410.iso / hity wydania / Ubuntu 9.10 PL / karmelkowy-koliberek-desktop-9.10-i386-PL.iso / casper / filesystem.squashfs / usr / bin / dh_pysupport < prev    next >
Text File  |  2009-05-13  |  11KB  |  363 lines

  1. #!/usr/bin/perl -w
  2.  
  3. =head1 NAME
  4.  
  5. dh_pysupport - use the python-support framework to handle Python modules
  6.  
  7. =cut
  8.  
  9. use strict;
  10. use File::Find;
  11. use Debian::Debhelper::Dh_Lib;
  12.  
  13. =head1 SYNOPSIS
  14.  
  15. B<dh_pysupport> [I<debhelper options>] [-V I<X.Y>] [-X I<item> [...]] [-n] [I<module dirs ...>]
  16.  
  17. =head1 DESCRIPTION
  18.  
  19. dh_pysupport is a debhelper program that will scan your package, detect
  20. public modules in I</usr/lib/pythonX.Y/site-packages>, and move them to 
  21. the shared Python modules location. It will generate appropriate
  22. postinst/prerm scripts to byte-compile modules installed there for all
  23. available python versions.
  24.  
  25. It will also look for private Python modules and will byte-compile them
  26. with the current Python version. You may have to list the directories
  27. containing private Python modules.
  28.  
  29. If a file named I<debian/pyversions> exists, it is used to determine the
  30. python versions with which the package can work.
  31.  
  32. Appropriate dependencies on python-support, python and pythonI<X.Y> are
  33. put in ${python:Depends}.  The ${python:Versions} and ${python:Provides} 
  34. optional substitution variables are made available as well.
  35.  
  36. =head1 OPTIONS
  37.  
  38. =over 4
  39.  
  40. =item I<module dirs>
  41.  
  42. If your package installs private python modules in non-standard directories, you
  43. can make dh_pysupport check those directories by passing their names on the
  44. command line. By default, it will check /usr/lib/$PACKAGE,
  45. /usr/share/$PACKAGE, /usr/lib/games/$PACKAGE and /usr/share/games/$PACKAGE
  46.  
  47. =item B<-n>, B<--noscripts>
  48.  
  49. Do not modify postinst/postrm scripts.
  50.  
  51. =item B<-d>
  52.  
  53. This option is deprecated.
  54.  
  55. =item B<-V> I<X.Y>
  56.  
  57. Force private modules to be bytecompiled with the specific I<X.Y> python version, regardless of the default python version on the system.
  58.  
  59. =item B<-X> I<item>, B<--exclude=>I<item>
  60.  
  61. Exclude files that contain "item" anywhere in their filename from being
  62. taken into account to generate the python dependency. It also excludes 
  63. them from byte-compilation. You may use this option multiple times to 
  64. build up a list of things to exclude.
  65.  
  66. =back
  67.  
  68. =head1 CONFORMS TO
  69.  
  70. Python policy as of 2006-08-10
  71.  
  72. =cut
  73.  
  74. init();
  75.  
  76. sub next_minor_version {
  77.     my $version = shift;
  78.     # Handles 2.10 -> 2.11 gracefully
  79.     my @items = split(/\./, $version);
  80.     $items[1] += 1;
  81.     $version = join(".", @items);
  82.     return $version;
  83. }
  84.  
  85. sub specified_deps_in_package {
  86.     my $package = shift;
  87.     my $curpackage = 0;
  88.     my @deps = ();
  89.     open (CONTROL, 'debian/control') || error("cannot read debian/control: $!\n");
  90.     while (<CONTROL>) {
  91.         chomp;
  92.         s/\s+$//;
  93.         if (/^Package:\s*(.*)$/ && $package eq $1) {
  94.             $curpackage = 1;
  95.         }
  96.         if ($curpackage == 2) {
  97.             if (/^\s+(.*)$/) {
  98.                 push @deps, split ",",$1;
  99.                 if ($1 !~ /,$/) {
  100.                     return @deps;
  101.                 }
  102.             } else {
  103.                 return @deps;
  104.             }
  105.         }
  106.         if ($curpackage && /^Python-Depends:\s*(.*)$/) {
  107.             @deps = split ",",$1;
  108.             if ($1 =~ /,$/) {
  109.                 $curpackage = 2;
  110.             } else {
  111.                 return @deps;
  112.             }
  113.         }
  114.     }
  115.     return @deps;
  116. }
  117.  
  118. sub trim {
  119.     my $tmp = shift;
  120.     $tmp =~ s/^\s+//;
  121.     $tmp =~ s/\s+$//;
  122.     return $tmp;
  123. }
  124.  
  125. # The current default python version
  126. my $default=`readlink /usr/bin/python`;
  127. $default =~ s/^python//;
  128. chomp $default;
  129.  
  130. my $privdir="/usr/share/python-support/private";
  131. # All supported versions
  132. my $allversions_string=`$privdir/parseversions --all`;
  133. chomp $allversions_string;
  134. my @allversions=split " ", $allversions_string;
  135.  
  136. # Use a specific version for private modules (doesn't affect public modules)
  137. my $useversion;
  138. if($dh{V_FLAG_SET}) {
  139.     $useversion = $dh{V_FLAG};
  140.     if (! grep { $_ eq $useversion } @allversions) {
  141.         error("Unknown python version $useversion");
  142.     }
  143. }
  144.  
  145. foreach my $package (@{$dh{DOPACKAGES}}) {
  146.     my $tmp = tmpdir($package);
  147.     my $have_pydep=0; # This variable tells whether we have added some dependency
  148.               # on python one way or another.
  149.     my @specified_deps = specified_deps_in_package ($package);
  150.     my $do_scripts = "";
  151.     
  152.     # 1) Handle public python modules
  153.     # Move them to the python-support directories
  154.     my $verfile = "debian/pyversions";
  155.     my $versions = "";
  156.     if (-f $verfile) {
  157.         # TODO: debian/package.pyversions ?
  158.         $versions=`cat $verfile`;
  159.         chomp $versions;
  160.     } else {
  161.         my $doko_versions=`$privdir/parseversions --raw --pycentral debian/control`;
  162.         chomp $doko_versions;
  163.         if ($doko_versions !~ /not found/) {
  164.             $versions=$doko_versions;
  165.         }
  166.     }
  167.     if ($versions) {
  168.         doit (("$privdir/movemodules","-V", $versions, $tmp))
  169.     } else {
  170.         doit (("$privdir/movemodules",$tmp));
  171.     }
  172.  
  173.     # Then look for what the script found
  174.     foreach my $list_file (glob("$tmp/usr/share/python-support/*.public")) {
  175.         if (-f $list_file) {
  176.                 my $supported=`$privdir/parseversions --minmax $list_file`;
  177.  
  178.                 # Add the packages explicitly asked by the maintainer
  179.                 foreach my $dep (@specified_deps) {
  180.                     $dep = trim $dep;
  181.                     addsubstvar($package, "python:Depends", $dep);
  182.                 }
  183.                 my @ar=split "\n",$supported;
  184.                 my @provides=split " ",$ar[0];
  185.                 foreach my $pyversion (@provides) {
  186.                     # Generate the useless versions field
  187.                     addsubstvar($package, "python:Versions", $pyversion);
  188.                     # ... and the provides field
  189.                 if ($package =~ /^python-/) {
  190.                         my $virtual = $package;
  191.                     $virtual =~ s/^python-/python$pyversion-/;
  192.                     addsubstvar($package, "python:Provides", $virtual);
  193.                     }
  194.                     # Use the provides fields in packages dependended upon
  195.                     foreach my $dep (@specified_deps) {
  196.                     $dep = trim $dep;
  197.                         # I have no idea why this wouldn't be the case, but well
  198.                         if ($dep =~ /^python-(\S+)/) {
  199.                             addsubstvar($package, "python:Depends", "python$pyversion-$1");
  200.                         }
  201.                     }
  202.                 }
  203.                    my @minmax=split " ",$ar[1];
  204.                    my $minversion=$minmax[0];
  205.                 if ( grep { $_ eq $default } @provides ) {
  206.                     # The default version is in the supported versions
  207.                     if ($minversion ne "None") {
  208.                         addsubstvar($package, "python:Depends", "python (>= $minversion)");
  209.                     $have_pydep=1;
  210.                     }
  211.                 } elsif ($minversion ne "None") {
  212.                     # The default version is less than all supported versions
  213.                     addsubstvar($package, "python:Depends", "python (>= $minversion) | python$minversion");
  214.                 $have_pydep=1;
  215.                 } else {
  216.                     error("The default python version is greater than all supported versions");
  217.                 }
  218.                 my $maxversion=$minmax[1];
  219.                 if ($maxversion ne "None") {
  220.                 $maxversion = next_minor_version($maxversion);
  221.                 addsubstvar($package, "python:Depends", "python (<< $maxversion)");
  222.                 $have_pydep=1;
  223.             }
  224.             $list_file =~ s,^$tmp/usr/share/python-support/,,;
  225.             $do_scripts = "$do_scripts $list_file";
  226.         }
  227.     }
  228.  
  229.         # 2) Look for private python modules
  230.     my @dirs = ("/usr/lib/$package", "/usr/share/$package",
  231.             "/usr/lib/games/$package", "/usr/share/games/$package", @ARGV );
  232.     @dirs = grep -d, map "$tmp$_", @dirs;
  233.         my @filelist;
  234.         my $file;
  235.         my $has_module = 0;
  236.         my $has_extension = 0;
  237.         my $need_pydep=0;
  238.         my $strong_pydep=0;
  239.     my %need_verdep = ();
  240.     foreach (@allversions) {
  241.         $need_verdep{$_} = 0;
  242.     }
  243.         if (@dirs) {
  244.                 foreach my $curdir (@dirs) {
  245.                         find sub {
  246.                                 return unless -f;
  247.                                 return if excludefile($File::Find::name);
  248.                                 if (/\.py$/) {
  249.                                     $has_module=1;
  250.                                     doit(("rm","-f",$_."c",$_."o"));
  251.                                     ( $file=$File::Find::name ) =~ s%^$tmp%%;
  252.                                     if (! grep { $_ eq $file } @filelist) {
  253.                                         push @filelist, $file;
  254.                                     }
  255.                                 }
  256.                                 if (/\.so$/ &&
  257.                                     `nm -Du "$_" | grep "U Py_InitModule"` &&
  258.                                     ! `objdump -p "$_" | grep "NEEDED *libpython"`) {
  259.                                     $has_extension=1;
  260.                                 }
  261.                         }, $curdir ;
  262.                 }
  263.         }
  264.  
  265.         if ( ($has_module or $has_extension) ) {
  266.                 if ( $useversion ) {
  267.                     $need_verdep{$useversion}=1;
  268.                 } else {
  269.                     $need_pydep=1;
  270.                     $strong_pydep=1 if $has_extension;
  271.                 }
  272.         }
  273.  
  274.     if (@filelist) {
  275.         # We have private python modules
  276.         # Use python-support to ensure that they are always
  277.         # byte-compiled for the current version
  278.         mkdir("$tmp/usr/share/python-support");
  279.         open(FILELIST, "> $tmp/usr/share/python-support/$package.private") ||
  280.             error("Can't create $tmp/usr/share/python-support/$package.private: $!");
  281.         if ( $useversion ) {
  282.                 print FILELIST "pyversion=$useversion\n\n";
  283.         }
  284.         print FILELIST map "$_\n", @filelist;
  285.         close(FILELIST);
  286.         $do_scripts = "$do_scripts $package.private";
  287.     }
  288.  
  289.     # 3) Add python-support dependency depending on what we found
  290.     if (-d "$tmp/usr/share/python-support") {
  291.             addsubstvar($package, "python:Depends", "python-support (>= 0.90.0)");
  292.     }
  293.  
  294.            # 4) Look for python scripts
  295.            find sub {
  296.         return unless -f and -x;
  297.         return if excludefile($File::Find::name);
  298.         local *F;
  299.                return unless open F, $_;
  300.         if (read F, local $_, 32 and m%^#!\s*/usr/bin/(env\s+)?(python(\d+\.\d+)?)\s%) {
  301.                    if ( "python" eq $2 ) {
  302.                 $need_pydep=1;
  303.                    } elsif (defined $need_verdep{$3}) {
  304.                        $need_verdep{$3}=1;
  305.                    }
  306.                }
  307.                close F;
  308.            }, $tmp;
  309.            
  310.            # 5) Generate remaining dependencies
  311.            foreach (@allversions) {
  312.                if ($need_verdep{$_}) {
  313.                    addsubstvar($package, "python:Depends", "python$_");
  314.                }
  315.            }
  316.            if (not $have_pydep) {
  317.                if ($strong_pydep) {
  318.                    addsubstvar($package, "python:Depends", "python (>= $default)");
  319.                    my $maxversion = next_minor_version($default);
  320.                    addsubstvar($package, "python:Depends", "python (<< $maxversion)");
  321.                    $have_pydep=1;
  322.                } elsif ($need_pydep and $versions) {
  323.                    my $supported=`echo $versions | $privdir/parseversions --minmax`;
  324.                    my @ar=split "\n",$supported;
  325.                    my @minmax=split " ",$ar[1];
  326.                 my $minversion=$minmax[0];
  327.                 if ($minversion ne "None") {
  328.                     addsubstvar($package, "python:Depends", "python (>= $minversion)");
  329.                     $have_pydep=1;
  330.             }
  331.             my $maxversion=$minmax[1];
  332.                 if ($maxversion ne "None") {
  333.                 $maxversion = next_minor_version($maxversion);
  334.                 addsubstvar($package, "python:Depends", "python (<< $maxversion)");
  335.                 $have_pydep=1;
  336.             }
  337.                }
  338.            }
  339.            # If nothing has added a python dependency yet, add it
  340.     if ($need_pydep and not $have_pydep) {
  341.                addsubstvar($package, "python:Depends", "python");
  342.     }
  343.     
  344.     # 6) Generate the scripts
  345.     if ($do_scripts && ! $dh{NOSCRIPTS}) {
  346.         autoscript($package, "postinst", "postinst-python-support", "s,#ARGS#,$do_scripts,");
  347.         autoscript($package, "prerm",    "prerm-python-support",    "s,#ARGS#,$do_scripts,");
  348.     }
  349. }
  350.  
  351. =head1 SEE ALSO
  352.  
  353. L<debhelper(7)>
  354.  
  355. This program is a part of python-support but is made to work with debhelper.
  356.  
  357. =head1 AUTHORS
  358.  
  359. Josselin Mouette <joss@debian.org>,
  360. Raphael Hertzog <hertzog@debian.org>
  361.  
  362. =cut
  363.